package ast

import (
	"bytes"
	"fmt"
	"lark/src/lexer"
	"strconv"
	"strings"
)

// 节点
type Node interface {
	TokenLiteral() string
	//调试
	String() string
}

// 语句
type Statement interface {
	Node
	statementNode()
}

// 表达式节点
type Expression interface {
	Node
	expressionNode()
}

// 根节点
type Program struct {
	Statements []Statement
}

func (p *Program) TokenLiteral() string {
	if len(p.Statements) > 0 {
		return p.Statements[0].TokenLiteral()
	} else {
		return ""
	}
}
func (p *Program) String() string {
	// var out bytes.Buffer
	str := "[\n"
	for _, s := range p.Statements {
		// out.WriteString(s.String())
		str += s.String() + "\n"
	}
	str += "]"
	// return out.String()
	return str
}

type LetStatement struct {
	Token lexer.Token
	Name  *Identifier
	Value Expression
}

func (ls *LetStatement) statementNode()       {}
func (ls *LetStatement) TokenLiteral() string { return ls.Token.Literal }
func (ls *LetStatement) String() string {
	/* var out bytes.Buffer

	out.WriteString(ls.TokenLiteral() + " ")
	out.WriteString(ls.Name.String())
	out.WriteString(" = ")
	if ls.Value != nil {
		out.WriteString(ls.Value.String())
	}
	out.WriteString(";")
	return out.String() */
	tok := "{Type:" + string(ls.Token.Type) + ",Literal:" + ls.Token.Literal + "}"
	value := "{Node:,expressionNode:" + ls.Value.String() + "}"
	return "LetStatement:{\nToken:" + tok + ",\nName:" + ls.Name.String() + ",\nValue:" + value + "\n}"
}

type AssignStatement struct {
	Token lexer.Token
	Name  *Identifier
	Value Expression
}

func (ls *AssignStatement) statementNode()       {}
func (ls *AssignStatement) TokenLiteral() string { return ls.Token.Literal }
func (ls *AssignStatement) String() string {
	tok := "{Type:" + string(ls.Token.Type) + ",Literal:" + ls.Token.Literal + "}"
	value := "{Node:,expressionNode:" + ls.Value.String() + "}"
	return "AssignStatement:{\nToken:" + tok + ",\nName:" + ls.Name.String() + ",\nValue:" + value + "\n}"
}

type ExpressionStatement struct {
	Token      lexer.Token
	Expression Expression
}

func (es *ExpressionStatement) statementNode()       {}
func (es *ExpressionStatement) TokenLiteral() string { return es.Token.Literal }

func (es *ExpressionStatement) String() string {
	tok := "{Type:" + string(es.Token.Type) + ",Literal:" + es.Token.Literal + "}"
	return "ExpressionStatement:{\nToken:" + tok + ",\nExpression:" + es.Expression.String() + "\n},"
}

type PrefixExpression struct {
	Token    lexer.Token // The prefix token, e.g. !
	Operator string
	Right    Expression
}

func (pe *PrefixExpression) expressionNode()      {}
func (pe *PrefixExpression) TokenLiteral() string { return pe.Token.Literal }
func (pe *PrefixExpression) String() string {
	tok := "{Type:" + string(pe.Token.Type) + ",Literal:" + pe.Token.Literal + "}"
	return "{\nToken:" + tok + ",\nOperator:" + pe.Operator + ",\nRight:" + pe.Right.String() + "\n},"
}

type InfixExpression struct {
	Token    lexer.Token // The operator token, e.g. +
	Left     Expression
	Operator string
	Right    Expression
}

func (ie *InfixExpression) expressionNode()      {}
func (ie *InfixExpression) TokenLiteral() string { return ie.Token.Literal }
func (ie *InfixExpression) String() string {
	// fmt.Println(ie.Left)
	tok := "{Type:" + string(ie.Token.Type) + ",Literal:" + ie.Token.Literal + "}"
	return "InfixExpression:{Token:" + tok + ",Left:" + ie.Left.String() + ",Operator:" + ie.Operator + ",Right:" + ie.Right.String() + "}"
}

// 标识符（变量名）
type Identifier struct {
	Token lexer.Token
	Value string
}

func (i *Identifier) expressionNode()      {}
func (i *Identifier) TokenLiteral() string { return i.Token.Literal }
func (i *Identifier) String() string {
	tok := "{Type:" + string(i.Token.Type) + ",Literal:" + i.Token.Literal + "}"
	return "Identifier:{Token:" + tok + ",Value:" + i.Value + "}"
}

type Boolean struct {
	Token lexer.Token
	Value bool
}

func (b *Boolean) expressionNode()      {}
func (b *Boolean) TokenLiteral() string { return b.Token.Literal }
func (b *Boolean) String() string       { return b.Token.Literal }

// 整数
type IntegerLiteral struct {
	Token lexer.Token
	Value int64
}

func (i *IntegerLiteral) expressionNode()      {}
func (i *IntegerLiteral) TokenLiteral() string { return i.Token.Literal }
func (i *IntegerLiteral) String() string {
	tok := "{Type:" + string(i.Token.Type) + ",Literal:" + i.Token.Literal + "}"
	return "IntegerLiteral:{Token:" + tok + ",Value:" + strconv.Itoa(int(i.Value)) + "}"
}

// 浮点数
type FloatLiteral struct {
	Token lexer.Token
	Value float64
}

func (f *FloatLiteral) expressionNode()      {}
func (f *FloatLiteral) TokenLiteral() string { return f.Token.Literal }
func (f *FloatLiteral) String() string       { return strconv.FormatFloat(f.Value, 'f', -1, 64) }

// 字符串
type StringLiteral struct {
	Token lexer.Token
	Value string
}

func (s *StringLiteral) expressionNode()      {}
func (s *StringLiteral) TokenLiteral() string { return s.Token.Literal }
func (s *StringLiteral) String() string {
	var out bytes.Buffer

	tok := "{Type:" + string(s.Token.Type) + ",Literal:" + s.Token.Literal + "}"
	out.WriteString("StringLiteral:{")
	out.WriteString("Token:" + tok + ",Value:" + s.Value + "}")
	out.WriteString("}")

	return out.String()
}

type ReturnStatement struct {
	Token       lexer.Token // the 'return' token
	ReturnValue Expression
}

func (rs *ReturnStatement) statementNode()       {}
func (rs *ReturnStatement) TokenLiteral() string { return rs.Token.Literal }
func (rs *ReturnStatement) String() string {
	var out bytes.Buffer

	out.WriteString(rs.TokenLiteral() + " ")

	if rs.ReturnValue != nil {
		out.WriteString(rs.ReturnValue.String())
	}

	out.WriteString(";")

	return out.String()
}

type IfExpression struct {
	Token       lexer.Token // The 'if' token
	Condition   Expression  //条件
	Consequence *BlockStatement
	Alternative *BlockStatement //else中的代码
}

func (ie *IfExpression) expressionNode()      {}
func (ie *IfExpression) TokenLiteral() string { return ie.Token.Literal }
func (ie *IfExpression) String() string {
	var out bytes.Buffer

	out.WriteString("if")
	out.WriteString(ie.Condition.String())
	out.WriteString(" ")
	out.WriteString(ie.Consequence.String())

	if ie.Alternative != nil {
		out.WriteString("else ")
		out.WriteString(ie.Alternative.String())
	}

	return out.String()
}

type ForExpression struct {
	Token        lexer.Token   // The 'for' token
	InitialValue *LetStatement //初始值 let i=1
	Condition    Expression    //条件 i<=5
	Increment    Expression    //增量 i++
	Body         *BlockStatement
}

func (fe *ForExpression) expressionNode()      {}
func (fe *ForExpression) TokenLiteral() string { return fe.Token.Literal }
func (fe *ForExpression) String() string {
	var out bytes.Buffer

	out.WriteString("for")

	return out.String()
}

// 块语句
type BlockStatement struct {
	Token      lexer.Token // the { token
	Statements []Statement
}

func (bs *BlockStatement) statementNode()       {}
func (bs *BlockStatement) TokenLiteral() string { return bs.Token.Literal }
func (bs *BlockStatement) String() string {
	statements := ""
	for _, s := range bs.Statements {
		statements += s.String()
	}
	tok := "{Type:" + string(bs.Token.Type) + ",Literal:" + bs.Token.Literal + "}"
	return "BlockStatement:{Token:" + tok + ",Statements:[" + statements + "]}"
}

type FunctionLiteral struct {
	Token      lexer.Token // The 'fn' token
	Name       string
	Parameters []*Identifier
	Body       *BlockStatement
}

func (fl *FunctionLiteral) expressionNode()      {}
func (fl *FunctionLiteral) TokenLiteral() string { return fl.Token.Literal }
func (fl *FunctionLiteral) String() string {
	var out bytes.Buffer

	params := []string{}
	for _, p := range fl.Parameters {
		params = append(params, p.String())
	}

	out.WriteString(fl.TokenLiteral())
	out.WriteString("(")
	out.WriteString(strings.Join(params, ", "))
	out.WriteString(") ")
	out.WriteString(fl.Body.String())

	// return out.String()
	tok := "{Type:" + string(fl.Token.Type) + ",Literal:" + fl.Token.Literal + "}"
	return "FunctionLiteral:{Token:" + tok + ",Parameters:" + out.String() + ",Body:''}"
}

// 调用函数表达式
type CallExpression struct {
	Token     lexer.Token // The '(' token
	Function  Expression  // Identifier or FunctionLiteral
	Arguments []Expression
}

func (ce *CallExpression) expressionNode()      {}
func (ce *CallExpression) TokenLiteral() string { return ce.Token.Literal }
func (ce *CallExpression) String() string {
	var out bytes.Buffer

	args := []string{}
	for _, a := range ce.Arguments {
		args = append(args, a.String())
	}

	out.WriteString(ce.Function.String())
	out.WriteString("(")
	out.WriteString(strings.Join(args, ", "))
	out.WriteString(")")

	// return out.String()
	tok := "{Type:" + string(ce.Token.Type) + ",Literal:" + ce.Token.Literal + "}"
	return "CallExpression:{Token:" + tok + ",Function:" + ce.Function.String() + ",Arguments:" + out.String() + "}"
}

type ArrayLiteral struct {
	Token    lexer.Token // the '[' token
	Elements []Expression
}

func (al *ArrayLiteral) expressionNode()      {}
func (al *ArrayLiteral) TokenLiteral() string { return al.Token.Literal }
func (al *ArrayLiteral) String() string {
	var out bytes.Buffer

	elements := []string{}
	for _, el := range al.Elements {
		elements = append(elements, el.String())
	}

	out.WriteString("[")
	out.WriteString(strings.Join(elements, ", "))
	out.WriteString("]")

	return out.String()
}

type IndexExpression struct {
	Token lexer.Token // The [ token
	Left  Expression
	Index Expression
	// Right AssignStatement
	Right Expression
}

func (ie *IndexExpression) expressionNode()      {}
func (ie *IndexExpression) TokenLiteral() string { return ie.Token.Literal }
func (ie *IndexExpression) String() string {
	var out bytes.Buffer

	out.WriteString("(")
	out.WriteString(ie.Left.String())
	out.WriteString("[")
	out.WriteString(ie.Index.String())
	out.WriteString("])")

	return out.String()
}

type HashLiteral struct {
	Token lexer.Token // the '{' token
	Pairs map[Expression]Expression
}

func (hl *HashLiteral) expressionNode()      {}
func (hl *HashLiteral) TokenLiteral() string { return hl.Token.Literal }
func (hl *HashLiteral) String() string {
	var out bytes.Buffer

	pairs := []string{}
	for key, value := range hl.Pairs {
		pairs = append(pairs, key.String()+":"+value.String())
	}

	out.WriteString("{")
	out.WriteString(strings.Join(pairs, ","))
	out.WriteString("}")

	return out.String()
}

type ImportStatement struct {
	Token     lexer.Token
	Name      *Identifier //包名称
	AliasName *Identifier //别名
	Path      string      //文件路径
}

func (i *ImportStatement) statementNode() {}

func (i *ImportStatement) TokenLiteral() string {
	/* if len(i.Statements) > 0 {
		return i.Statements[0].TokenLiteral()
	} else {
		return ""
		} */
	return i.Token.Literal
}

func (i *ImportStatement) String() string {
	var out bytes.Buffer

	out.WriteString("{")
	// out.WriteString(i.Token)
	out.WriteString(i.Path)
	out.WriteString("}")

	return out.String()

	// return "ImportStatement:{\nToken:" + tok + ",\nName:" + ls.Name.String() + ",\nValue:" + value + "\n}"
}

/* func (p *ImportLiteral) String() string {
	// var out bytes.Buffer
	str := "[\n"
	for _, s := range p.Statements {
		// out.WriteString(s.String())
		str += s.String() + "\n"
	}
	str += "]"
	// return out.String()
	return str
} */

// math.query();

// 模块访问表达式 api.name
type ModuleAccess struct {
	Token  lexer.Token // 保存 '.' token
	Module *Identifier // 模块名称
	Name   *Identifier // 模块中的变量名或函数名
}

func (ma *ModuleAccess) expressionNode()      {}
func (ma *ModuleAccess) TokenLiteral() string { return ma.Token.Literal }
func (ma *ModuleAccess) String() string {
	tok := "{Type:" + string(ma.Token.Type) + ",Literal:" + ma.Token.Literal + "}"
	return fmt.Sprintf("ModuleAccess:{Token:%s,Module:%s,Name:%s}", tok, ma.Module.String(), ma.Name.String())
}

// 点操作表达式AST节点
type DotExpression struct {
	Token lexer.Token // The . token
	Left  Expression
	Right *Identifier
}

func (de *DotExpression) expressionNode()      {}
func (de *DotExpression) TokenLiteral() string { return de.Token.Literal }
func (de *DotExpression) String() string {
	return fmt.Sprintf("%s.%s", de.Left.String(), de.Right.String())
}

// 对象属性访问表达式 result.name
type ObjectPropertyAccess struct {
	Token    lexer.Token //
	Object   Expression  // 可以是标识符或其他表达式
	Property *Identifier // 属性名
}

func (o *ObjectPropertyAccess) expressionNode()      {}
func (o *ObjectPropertyAccess) TokenLiteral() string { return o.Token.Literal }
func (o *ObjectPropertyAccess) String() string {
	tok := "{Type:" + string(o.Token.Type) + ",Literal:" + o.Token.Literal + "}"
	return fmt.Sprintf("ObjectPropertyAccess:{Token:%s,Object:%s,Property:%s}", tok, o.Object.String(), o.Property.String())
}

// 模块，属性，统一属性/方法访问表达式
type AccessExpression struct {
	Token    lexer.Token  //
	Left     Expression   // 左侧表达式 (request 或 req)
	Property *Identifier  // 属性名 (get 或 status)
	Call     bool         // 是否是方法调用
	Args     []Expression // 调用参数
}

func (a *AccessExpression) expressionNode()      {}
func (a *AccessExpression) TokenLiteral() string { return a.Token.Literal }
func (a *AccessExpression) String() string {
	tok := "{Type:" + string(a.Token.Type) + ",Literal:" + a.Token.Literal + "}"
	return fmt.Sprintf("AccessExpression:{Token:%s,Left:%s,Property:%s,Call:%s,Args:%s}", tok, a.Left.String(), a.Property.String(), fmt.Sprintf("%v", a.Call), a.Args)
}
